package com.min.license;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import com.alibaba.fastjson.JSONObject;
import com.min.license.config.LicenseProperties;
import com.min.license.entity.License;
import com.min.license.exception.LicenseException;

import java.io.*;

public class LicenseManager {

    static final String MAGIC = "mlicense";

    LicenseProperties properties;

    public LicenseManager(LicenseProperties conf) {
        this.properties = conf;
    }

    public byte[] encode(License l, String publicKey, String privateKey) {
        try (ByteArrayOutputStream baOs = new ByteArrayOutputStream()) {
            baOs.write(MAGIC.getBytes());
            try (ObjectOutputStream objOs = new ObjectOutputStream(baOs)) {
                final String licenseString = JSONObject.toJSONString(l);
                RSA rsa = new RSA(null, publicKey);
                final byte[] secret = rsa.encrypt(licenseString, KeyType.PublicKey);
                objOs.writeInt(secret.length);
                objOs.write(secret);

                final byte[] privateKeyBytes = privateKey.getBytes();
                objOs.writeInt(privateKeyBytes.length);
                objOs.write(privateKeyBytes);

                objOs.flush();
                baOs.flush();
                return baOs.toByteArray();
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    public License decode(byte[] license) throws IOException {
        try (ByteArrayInputStream byteIs = new ByteArrayInputStream(license)) {
            byte[] magicBytes = new byte[MAGIC.length()];
            byteIs.read(magicBytes);
            if (!MAGIC.equals(new String(magicBytes))) {
                throw new LicenseException("非法许可");
            }

            try (ObjectInputStream obj = new ObjectInputStream(byteIs)) {
                byte[] secret = new byte[obj.readInt()];
                obj.read(secret);

                byte[] privateKey = new byte[obj.readInt()];
                obj.read(privateKey);

                RSA rsa = new RSA(StrUtil.str(privateKey, CharsetUtil.CHARSET_UTF_8), null);
                final byte[] decrypt = rsa.decrypt(secret, KeyType.PrivateKey);

                final String str = StrUtil.str(decrypt, CharsetUtil.CHARSET_UTF_8);

                return JSONObject.parseObject(str, License.class);
            }
        }
    }

    public long check() throws LicenseException, IOException {
        String filePath = properties.getPath() + "/license";
        if (!FileUtil.exist(filePath)) {
            throw new LicenseException("license未找到，路径：" + properties.getPath());
        }

        final byte[] bytes = FileUtil.readBytes(filePath);
        final License license = this.decode(bytes);
        if (license == null) {
            throw new LicenseException("非法许可");
        }
        return license.getExpire() - (System.currentTimeMillis() - license.getStart());
    }

}
